package sii.challenge.predictors;

import sii.challenge.dataset.Dataset;

/**
 * 
 * Effettua predizioni circa i rating che gli user (gli utenti) esprimerebbero
 * per gli item (i profili). Maggiori informazioni nel materiale allegato al
 * progetto.
 * 
 * @author Marco Liceti
 * 
 */
public final class SimplePredictor implements Predictor {

	private static SimplePredictor instance;

	private static final int alpha = 20;

	private Dataset dataset;

	private SimplePredictor(Dataset dataset) {
		this.dataset = dataset;
	}

	/**
	 * 
	 * Restituisce il SimplePredictor.
	 * 
	 * @param dataset
	 *            l'oggetto Dataset che consente di ricavare informazioni
	 *            necessarie per la predizione.
	 * 
	 * @return il SimplePredictor
	 * 
	 */
	public static SimplePredictor getInstance(Dataset dataset) {
		if (instance == null) {
			instance = new SimplePredictor(dataset);
		}
		return instance;
	}

	@Override
	public int predictRating(int user, int item) {
		String user_gender = dataset.getUserGender(user);
		String item_gender = dataset.getItemGender(item);

		int number_ratings_from_user = dataset.getNumberOfRatingsFromUser(user,
				item_gender);
		int number_ratings_for_item = dataset.getNumberOfRatingsForItem(item,
				user_gender);

		double average_rating_from_user = 0;
		switch (user_gender.charAt(0)) {
		case 'M':
			average_rating_from_user = 5.0316;
			break;
		case 'F':
			average_rating_from_user = 6.3572;
			break;
		case 'U':
			average_rating_from_user = 5.8564;
			break;
		}
		double average_rating_for_item = 0;
		switch (item_gender.charAt(0)) {
		case 'M':
			average_rating_for_item = 6.7049;
			break;
		case 'F':
			average_rating_for_item = 5.3550;
			break;
		case 'U':
			average_rating_for_item = 4.9306;
			break;
		}

		if (number_ratings_from_user >= alpha) {
			average_rating_from_user = dataset.getRatingsGivenAverage(user,
					item_gender);
		} else {
			number_ratings_from_user = dataset.getNumberOfRatingsFromUser(user);
			if (number_ratings_from_user >= alpha) {
				average_rating_from_user = dataset.getRatingsGivenAverage(user);
			}
		}

		if (number_ratings_for_item >= alpha) {
			average_rating_for_item = dataset.getRatingsReceivedAverage(item,
					user_gender);
		} else {
			number_ratings_for_item = dataset.getNumberOfRatingsForItem(item);
			if (number_ratings_for_item >= alpha) {
				average_rating_from_user = dataset
						.getRatingsReceivedAverage(item);
			}
		}

		double prediction = (average_rating_from_user + average_rating_for_item) / 2;
		return Utils.toRating(prediction);
	}

}
